package chp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;

class IOHandler {
	
	/*
	 * We check that:
	 * - the file exists (checked using exception)
	 * - the extension is correct
	 * about the content:
	 * - one line
	 * - n+2 elements, where n is the first number
	 * - all the elements are natural numbers (aka >0)
	 * - k is a valid number (<=n), we already check if it is >0
	 * 
	 * If everything is ok we return the data
	 */
	static WICInput decodeInputFile(String fileName) throws InputFileException {
		
		File file = new File(fileName);
		
		StringTokenizer st;
		
		// check file's extension
		st = new StringTokenizer(file.getName(),".");
		String tok = null;
		while(st.hasMoreTokens())
					tok = st.nextToken();
		if( !(tok.equals("WIC") || tok.equals("wic")) )
			System.err.println("[WARNING] The input file \""+file.getAbsolutePath()+"\" has the wrong extension \""+tok+"\" instead of \"WIC\" or \"wic\"");		

		String dataString = null;
		try {
			BufferedReader buffReader = new BufferedReader( new FileReader(file) );
			dataString = buffReader.readLine();
		
			/*
			 * check if we have only one line
			 */
			if(buffReader.readLine()!=null)
				System.err.println("[WARNING] The input file \""+file.getAbsolutePath()+"\" contains more than one line");
		
			buffReader.close();
		} catch (IOException e) {
			throw new InputFileException("[ERROR] Input file \""+file.getAbsolutePath()+"\" not found or corrupted");
		}
		
		st = new StringTokenizer(dataString,",");
		
		//check if we have at least 3 elements (the minimum)
		if(st.countTokens()<3)
			throw new InputFileException("[ERROR] The input file \""+file.getAbsolutePath()+"\" does not contain valid data");
		
		//initialize the containers for the data and helper variables
		int N,K = -1;
		int[] ySet = null;
		int number = -1;
		String token = null;
	
		/*
		 * extract "n" and check if we have n+2 elements
		 */
		token = st.nextToken();		
		try {
			number = Integer.parseInt(token);
		} catch (NumberFormatException e) {
			throw new InputFileException("[ERROR] Wrong number format ("+token+")");
		}
		
		if(number<0)
			throw new InputFileException("[ERROR] Not-natural-number found ("+token+")");
		if(st.countTokens() < number+1) //we should find n+1 elements more
			throw new InputFileException("[ERROR] The input file \""+file.getAbsolutePath()+"\" does not contain valid data");
		if(st.countTokens() > number+1) //more than n+1 elements remaining
			throw new InputFileException("[ERROR] Data contains more than \"n\" numbers -- Invalid dataset");
		//if we are here n is valid, we will have n+2 elements thus we can proceed
		N = number; // store "n"	
		
		/*
		 * extract K 
		 */
		token = st.nextToken();	
		try {
			number = Integer.parseInt(token);
		} catch (NumberFormatException e) {
			throw new InputFileException("[ERROR] Wrong number format ("+token+")");
		}
		if(number<0)
			throw new InputFileException("[ERROR] Not-natural-number found ("+token+")");
		if(number>N)
			throw new InputFileException("[ERROR] K is bigger than n");
		//if we are here K is valid
		K = number; //store "K"
		
		int counter = 0;
		ySet = new int[N];
		
		/*
		 * extract the remaining elements
		 */
		while(counter < N){
			token = st.nextToken();
			try {
				number = Integer.parseInt(token);
			} catch (NumberFormatException e) {
				throw new InputFileException("[ERROR] Wrong number format ("+token+")");
			}
			if(number<0)
				throw new InputFileException("[ERROR] Not-natural-number found ("+token+")");
			ySet[counter] = number;
			counter++;
		}
		System.out.println("[INFO] Input file \""+file.getName()+"\" loaded");
		
		return new WICInput(N,K,ySet);
	}

	/*
	 * This file is used to handle "solution" data coming from a "WSO" file
	 */
static WICOutput decodeOutputFile(String fileName) throws InputFileException {
		
		File file = new File(fileName);
		StringTokenizer st;
		
		// check file's extension
		st = new StringTokenizer(file.getName(),".");
		String tok = null;
		while(st.hasMoreTokens())
					tok = st.nextToken();
		if( !(tok.equals("WSO") || tok.equals("wso")) )
			System.err.println("[WARNING] The input file \""+file.getAbsolutePath()+" \"has the wrong extension \""+tok+"\" instead of \"WSO\" or \"wso\"");		

		BufferedReader buffReader = null;
		try {
			buffReader = new BufferedReader( new FileReader(file) );
		} catch (IOException e) {
			throw new InputFileException("[ERROR] Input file \""+file.getAbsolutePath()+"\" not found or corrupted");
		}
		
		Vector<int[]> data = new Vector<int[]>();
		String line,token = null;
		int intervals = 0;
		int a,b,c = -1;
		
		try {
			line = buffReader.readLine();
		
			while(line != null){
				st = new StringTokenizer(line,",");
				
				if(st.countTokens()!=3)//check if we have 3 elements
					throw new InputFileException("[ERROR] The input file \""+file.getAbsolutePath()+"\" does not contain valid data");
				
				a = Integer.parseInt(st.nextToken());
				b = Integer.parseInt(st.nextToken());
				c = Integer.parseInt(st.nextToken());
			
				if( (a>=b) || (a<0) || (b<0) || (c<=0) )
					throw new InputFileException("[ERROR] The input file \""+file.getAbsolutePath()
							+"\" does not contain valid data ("+ line +")");
				
				data.add(new int[]{a,b,c});
				intervals++;
				line = buffReader.readLine();
			}
			buffReader.close();
		} catch (IOException e1) {
			throw new InputFileException("[ERROR] Input file \""+file.getAbsolutePath()+"\" not found or corrupted");
		} catch (NumberFormatException e) {
			throw new InputFileException("[ERROR] Wrong number format ("+token+")");
		}
	
		System.out.println("[INFO] Input file \""+file.getName()+"\" loaded");
		
		return new WICOutput(data,intervals);
	}
	
	
	
	/*
	 *  This method outputs a file .WSO containing the solution for a certain input
	 */
	static void generateOutputFile(String fileName, WICOutput data) throws OutputFileException{
		
		// check output file's extension
		StringTokenizer st = new StringTokenizer(fileName,".");
		String tok = null;
		while(st.hasMoreTokens())
					tok = st.nextToken();
		if( !(tok.equals("WSO") || tok.equals("wso")) )
			System.err.println("[WARNING] The output file has the wrong extension \""+tok+"\" instead of \"WSO\" or \"wso\"");		
		
		Enumeration<int[]> intervals = data.getData().elements();
		
		File outputFile = new File(fileName);
		if(outputFile.exists())
			outputFile.renameTo(new File(fileName+".old"));
		
		try {
			outputFile.createNewFile();
		
			BufferedWriter bw = null;
			
			try {
				bw = new BufferedWriter(new FileWriter(outputFile));
			} catch (FileNotFoundException e) {
				throw new OutputFileException("[ERROR] Output file not found");
			}
			
			while(intervals.hasMoreElements()){
				bw.append(intArrayStringify(intervals.nextElement()));
			}
			
			bw.flush();
			bw.close();
		} catch (IOException e) {
			throw new OutputFileException("[ERROR] It is not possible to create the output file");
		}
		
		System.out.println("[INFO] Output file \""+outputFile.getAbsolutePath()+"\" written");
	}
	
	
	static String intArrayStringify(int[] array){
		String output = "";
		for(int i=0; i< array.length-1; i++)
			output += array[i]+",";
		output += array[array.length-1]+"\n";
		
		return output;
	}
	
	
	static String solutionPicture(String algName, WICInput iData, WICOutput oData){
		int n = iData.getN();
		int[] ySet = iData.getYSet();
		Enumeration<int[]> intervals = oData.getData().elements();
		String picture = "\n"+algName+"\n\n";
		
		if(n>30){
			System.err.println("[ERROR] Input too big. Graphical representation disabled");
			return "";
		}
		int i = 1;
		while(i <= n){
			picture += "   |";
			i++;
		}
		picture += "  \n";
		
		int[] temp = null;
		int a,b,c;
		
		int counter = 1;
		while(intervals.hasMoreElements()){
			temp = intervals.nextElement();
			a = temp[0];
			b = temp[1];
			c = temp[2];
			i=1;
			while(i <= n+1){
				if(i==a)
					if(i==1) picture +=  " ._|_";
					else picture += "._|_";					
				else if(i==b) 
					if(i<=n) picture += ". | ";
					else picture += ".   "+"c"+counter+++" = "+c;
				else if(i>a && i<b)
					picture += "__|_";
				else
					if(i==1) picture += "   | ";
					else if (i<=n) picture += "  | ";
					else picture += "    "+"c"+counter+++" = "+c;
				i++;
			}
			picture += "\n";
		}
		
		i = 1;
		while(i <= n){
			picture += "   |";
			i++;
		}
		picture += "  \n";
		
		String s,spaces = null;
		i = 0;
		picture += "   ";
		while(i < n){
			s = Integer.toString(ySet[i]);
			switch(s.length()){
				case 1:
					spaces = "   ";
					break;
				case 2:
					spaces = "  ";
					break;
				default:
					spaces = " ";					
			}
			picture += ySet[i]+spaces;
			i++;
		}
		picture += "  ";
		
		return picture;
	}
}
